• flask 示例

from flask import Flask

app = Flask(__name__)

if __name__ == '__main__':
    app.run()  # 启动 Flask

  • 源码分析

    1. 当请求过来执行 run 方法
    2. 执行 __call__ 方法的到 environ 参数: 请求相关的所有数据(由wsgi做了初步的封装),start_response 参数: 用于设置响应相关数据
    3. 执行 wsgi_api 方法
      1. 获取 environ 并对其进行二次封装,得到 ctx 对象
      2. 从 environ 中获取名称为 session 的 cookie,然后进行解密 + 返序列化,最后得到一个字典,然后赋值给 ctx.session
      3. 将 ctx 对象放入 __storage__ 字典(即: 上下文字典)中的指定线程或协程下的 stack 列表里
      4. 执行视图函数,返回相应的数据给浏览器
      5. 从上下文字典中获取session,加密+序列化,最后写入 cookie 中
      6. 清空上下文字典中对应线程的数据

class Flask(_PackageBoundObject):
    def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
run_simple(host, port, self, **options)
"""
run_simple(ip, 端口, 对象或方法, **options) 的说明:
                1. 启动 Flask 监听 host 所指定的 ip + port 所指定端口,如果有人访问则执行 self() 返回对应的数据给浏览器
                2. 当 对象 + () 执行的时候就会调用它所在的类中的 __call__ 方法,所以 self() 实际上是调用了 Flask 类中的 __call__ 方法
        """

    def __call__(self, environ, start_response):
"""
        :param environ: 请求相关的所有数据(由wsgi做了初步的封装)
        :param start_response: 用于设置响应相关数据
        """
return self.wsgi_app(environ, start_response)

    def wsgi_app(self, environ, start_response):
"""
 wsgi_app的步骤:
                1. 获取 environ 并对其进行二次封装,得到 ctx 对象
                2. 从 environ 中获取名称为 session 的 cookie,然后进行解密 + 返序列化,最后得到一个字典,然后赋值给 ctx.session
                3. 将 ctx 对象放入 __storage__ 字典(即: 上下文字典)中的指定线程或协程下的 stack 列表里
                4. 执行视图函数,返回相应的数据给浏览器
                5. 从上下文字典中获取session,加密+序列化,最后写入 cookie 中
                6. 清空上下文字典中对应线程的数据
        """

ctx = self.request_context(environ)
 """
ctx = RequestContext(self, environ) 的说明:
                1. 作用:
                    对 environ 进行二次封装,得到 ctx 对象
                1. 参数
                    self参数:其实是 app对象
                    environ参数:请求相关的原始数据
                2. ctx 对象下的两个重要属性:
                    ctx.request = app.request_class(environ)
                    ctx.session = None
                3. ctx 对象下的两个重要方法:
                    ctx.push()
                    ctx.auto_pop()
        """
        error = None
        try:
            try:
ctx.push()
"""
ctx.push() 的说明:
                    1. 从 environ 中获取名称为 session 的 cookie,然后进行解密 + 反序列化,最后得到一个字典,然后赋值给 ctx.session
                        obj = app.session_interface  # app.session_interface 是 SecureCookieSessionInterface 所实例化出来的对象,且 SecureCookieSessionInterface 下有两个重要的方法 open_session 读取session,save_session 保存session
                        ctx.session = obj.open_session()
                    2. 将 ctx 对象放入 __storage__ 字典(即: 上下文字典)中的指定线程或协程下的 stack 列表里
                """
response = self.full_dispatch_request()
"""
response = self.full_dispatch_request() 的说明:
                        1. 执行视图函数
                        2. 从 __storage__ 字典(即: 上下文字典)中获取session,然后进行加密+序列化,最后写入 cookie 中
                            obj = app.session_interface  # app.session_interface 是 SecureCookieSessionInterface 所实例化出来的对象,且 SecureCookieSessionInterface 下有两个重要的方法 open_session 读取session,save_session 保存session
                            obj.save_session()
                """
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            if self.should_ignore_error(error):
                error = None
ctx.auto_pop(error)
"""
ctx.auto_pop(error) 的说明:
                    清空上下文字典中对应线程或协程的数据
            """